package cn.tedu.charging.device.dao.repository.impl;

import cn.tedu.charging.device.dao.repository.ChargingStationCacheRepository;
import cn.tedu.charging.device.pojo.po.ChargingStationPO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.BoundGeoOperations;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Repository;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Repository("GEOANDShareHash")
public class ChargingStationCacheGEOANDShareHashRepositoryImpl implements ChargingStationCacheRepository {
    @Autowired
    private RedisTemplate redisTemplate;
    @Override
    public void saveStations2Redis(List<ChargingStationPO> stationPOS) {
        Map<Integer, Point> map = new HashMap<>();
        Map<Integer,ChargingStationPO> stationPOMap = new HashMap<>();
        for (ChargingStationPO stationPO : stationPOS){
            BigDecimal stationLng = stationPO.getStationLng();
            BigDecimal stationLat = stationPO.getStationLat();

            String lngEngineeringString = stationLng.toEngineeringString();
            Double lng = Double.parseDouble(lngEngineeringString);

            String latEngineeringString = stationLat.toEngineeringString();
            Double lat = Double.valueOf(latEngineeringString);

            Point point = new Point(lng,lat);
            Integer stationId = stationPO.getId();
            map.put(stationId,point);

            stationPOMap.put(stationId,stationPO);
        }
        BoundGeoOperations stations = redisTemplate.boundGeoOps("stations-geo");
        stations.add(map);
        HashOperations<String,Integer,ChargingStationPO> hashOperations = redisTemplate.opsForHash();
        hashOperations.putAll("station_info_hash_share",stationPOMap);
    }

    @Override
    public List<ChargingStationPO> getStationsFromRedis(Double longitude, Double latitude, Double distance) {
        BoundGeoOperations stations = redisTemplate.boundGeoOps("stations-geo");

        HashOperations<String,Integer,ChargingStationPO> hashOperations = redisTemplate.opsForHash();

        Circle circle = getCircle(longitude,latitude,distance);
        log.debug("查询半径为{}的圆",circle);
        GeoResults<RedisGeoCommands.GeoLocation<Integer>> radius = stations.radius(circle);
        log.debug("查询到的结果为:{}",radius);

        List<ChargingStationPO> stationPOS = new ArrayList<>();
        for (GeoResult<RedisGeoCommands.GeoLocation<Integer>> geoLocationGeoResult : radius) {
            RedisGeoCommands.GeoLocation<Integer> content = geoLocationGeoResult.getContent();
            Integer stationId = content.getName();

            ChargingStationPO stationPO = hashOperations.get("station_info_hash_share", stationId);
            stationPOS.add(stationPO);
        }
        log.debug("查询到的结果为:{}",stationPOS);
        return stationPOS;
    }

    private Circle getCircle(Double longitude,Double latitude,Double distance){
        Point point = new Point(longitude,latitude);
        Distance geoDistance = new Distance(distance, Metrics.KILOMETERS);
        Circle circle = new Circle(point, geoDistance);
        return circle;
    }
}
